package com.lq.javawebTest.core;

import com.lq.javawebTest.core.entity.HttpRequest;
import com.lq.javawebTest.core.entity.HttpResponse;
import com.lq.javawebTest.core.entity.Session;
import com.lq.javawebTest.core.inter.Filter;
import com.lq.javawebTest.core.inter.Servlet;
import com.lq.javawebTest.core.utils.HttpRequestHandler;
import com.lq.javawebTest.core.utils.HttpResponseHandler;
import com.lq.javawebTest.utils.IOUtils;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.UUID;

public class Server {
    public static void main(String[] args) throws Exception {
        //加载配置
        System.out.println("开始加载配置...");
//        Configuration.readConfiguration();

        // 启动一个服务器,监听本地8080端口
//        int port = 8080;
        ServerSocket serverSocket = new ServerSocket(Configuration.PORT);
        System.out.println("Server started on port " + Configuration.PORT);

        //写一个死循环，一直等着这个端口
        flag : while (true) {
            Socket accept = serverSocket.accept();

            // 获得输入流，将输入流转化为实例对象
            InputStream inputStream = accept.getInputStream();
            HttpRequest request = HttpRequestHandler.getRequest(inputStream);

            // 按照http协议的格式封装一个报文
            HttpResponse response = new HttpResponse();

            //获得输出流
            OutputStream outputStream = accept.getOutputStream();
            //巧妙之处在于将,由于每个请求处理的内容不一样，所以其body内容也不一样，所以我们把outputstream
            //封装到实体类当中
            response.setOutputStream(outputStream);

            String uri = request.getUri();


            for(Filter filter : Container.getFilters()){
                Boolean flag = filter.preFilter(request, response);
                if(!flag){
                    continue flag;
                }
            }

            //创建session的情况：
            //1.没有cookie,处理cookie
            //服务端给浏览器cookie,也就是如果客户端没有cookie，则就是第一次第一次访问服务端
            if(request.getHeader("Cookie") == null){
                createSession(response);
            }else{
                //2.有cookie，但是其中没有jsessionid，要创建
                String cookie = request.getHeader("Cookie");
                if(!cookie.contains("jsessionid=")){
                    createSession(response);
                }else{
                    //3.有jsessionid,但是找不到session，也要创建
                    String jsessionid = cookie.split("=")[1];
                    if(Container.getSession(jsessionid) == null){
                        createSession(response);
                    }
                }
            }

            //这里只是在理想状态下实现动态与静态资源分离，如果不包含.html则判断为动态资源，使用servlet进行处理
            if(uri.contains(".html")){
                //将要返回的网页内容的文件从本地读入到流，并转化为String实例（静态资源）
                String path  = Configuration.BASE_URL + request.getUri();
                String body = IOUtils.getContext(path);
                if(body != null){
                    response.setHeader("Content-Type","text/html;charset=UTF-8");
                    response.setHeader("Content-Length",Integer.toString(body.getBytes().length));
                    response.setBody(body);
                    // 将回复报文实例先转化为String实例，然后再写入到输出流给浏览器
                    HttpResponseHandler.writeResponse(response, outputStream);
                }
                //处理动态资源
            }else if(uri.contains(".do")){
                // 根据传入的uri不同，给出不同的响应，这里的Contanier是一个map容器，里面存储了应对不同uri所需要的servlet响应实例
                //而Srvlet又是一个父类接口，实际运行中根据实际不同的servlet实例，父类引用指向子类对象的多态
                Servlet servlet = Container.getServlet(request.getUri());
                if(servlet != null) {
                    servlet.service(request, response);
                }
            }

            //处理完业务之后，返回给浏览器之前进行的过滤
            for(Filter filter : Container.getFilters()){
                Boolean flag = filter.postFilter(request,response);
                if(!flag){
                    continue flag;
                }
            }

            // 这个输出流不要着急关，因为突然的关闭会导致浏览器和服务器的连接断开
//            inputStream.close();
//            outputStream.close();
//            accept.close();
        }
    }

    //抽离创建session的方法，减少代码冗余
    private static void createSession(HttpResponse response) {
        String jsessionid = UUID.randomUUID().toString();
        response.setHeader("set-Cookie","jsessionid=" + jsessionid);
        Container.addSession(jsessionid,new Session());
    }
}

